using System.Text;

namespace OracleInternal.Network
{
	internal class NVFactory
	{
		internal static NVPair CreateNVPair(string nvString)
		{
			NVTokens nVTokens = new NVTokens();
			nVTokens.ParseTokens(nvString);
			return ReadTopLevelNVPair(nVTokens);
		}

		private static NVPair ReadTopLevelNVPair(NVTokens nvt)
		{
			int token = nvt.Token;
			nvt.EatToken();
			if (token != 1)
			{
				_ = new object[2]
				{
					"(",
					GetContext(nvt)
				};
				throw new NetworkException(303);
			}
			string text = ReadNVLiteral(nvt);
			NVPair nVPair = new NVPair(text);
			if ((token = nvt.Token) == 3)
			{
				while (token == 8 || token == 3)
				{
					text += nvt.PopLiteral();
					token = nvt.Token;
				}
				nVPair.Name = text;
				return ReadRightHandSide(nVPair, nvt);
			}
			return ReadRightHandSide(nVPair, nvt);
		}

		private static NVPair ReadNVPair(NVTokens nvt)
		{
			int token = nvt.Token;
			nvt.EatToken();
			if (token != 1 && token != 3)
			{
				_ = new object[2]
				{
					"( or ,",
					GetContext(nvt)
				};
				throw new NetworkException(303);
			}
			return ReadRightHandSide(new NVPair(ReadNVLiteral(nvt)), nvt);
		}

		private static NVPair ReadRightHandSide(NVPair nvp, NVTokens nvt)
		{
			int token;
			switch (token = nvt.Token)
			{
			case 4:
				nvt.EatToken();
				token = nvt.Token;
				if (token == 8)
				{
					nvp.Atom = ReadNVAtom(nvt);
				}
				else
				{
					ReadNVList(nvt, nvp);
				}
				break;
			case 2:
			case 3:
				nvp.Atom = nvp.Name;
				break;
			default:
				_ = new object[2]
				{
					"=",
					GetContext(nvt)
				};
				throw new NetworkException(303);
			}
			switch (nvt.Token)
			{
			case 2:
				nvt.EatToken();
				break;
			default:
				_ = new object[2]
				{
					nvt.Literal,
					GetContext(nvt)
				};
				throw new NetworkException(303);
			case 3:
				break;
			}
			return nvp;
		}

		private static string ReadNVLiteral(NVTokens nvt)
		{
			if (nvt.Token != 8)
			{
				_ = new object[2]
				{
					"LITERAL",
					GetContext(nvt)
				};
				throw new NetworkException(303);
			}
			return nvt.PopLiteral();
		}

		private static string ReadNVAtom(NVTokens nvt)
		{
			int token = nvt.Token;
			if (token != 8)
			{
				_ = new object[2]
				{
					"LITERAL",
					GetContext(nvt)
				};
				throw new NetworkException(303);
			}
			StringBuilder stringBuilder = new StringBuilder();
			while (token != 2)
			{
				stringBuilder = stringBuilder.Append(nvt.PopLiteral());
				token = nvt.Token;
			}
			return stringBuilder.ToString();
		}

		private static void ReadNVList(NVTokens nvt, NVPair parent)
		{
			int token = nvt.Token;
			if (token == 1 || token == 3)
			{
				NVPair nVPair = ReadNVPair(nvt);
				parent.AddListElement(nVPair);
				if ((token == 3 || (object)nVPair.Name == nVPair.Atom) && parent.ListType != NVPair.LIST_COMMASEP)
				{
					parent.ListType = NVPair.LIST_COMMASEP;
				}
				ReadNVList(nvt, parent);
			}
		}

		private static string GetContext(NVTokens nvt)
		{
			return " " + nvt.PopLiteral() + " " + nvt.PopLiteral() + " " + nvt.PopLiteral();
		}
	}
}
